package com.lhz.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 任务执行工具
 *
 * @author LiGezZ
 */
public class JobInvokeUtil {
    /**
     * 执行方法
     *
     * @param invokeTarget 系统任务
     */
    public static void invokeMethod(String invokeTarget) throws Exception {
        String beanName = getBeanName(invokeTarget);
        String methodName = getMethodName(invokeTarget);
        List<Object[]> methodParams = getMethodParams(invokeTarget);

        Object bean = Class.forName(beanName).getConstructor().newInstance();
        invokeMethod(bean, methodName, methodParams);
    }

    /**
     * 调用任务方法
     *
     * @param bean         目标对象
     * @param methodName   方法名称
     * @param methodParams 方法参数
     */
    private static void invokeMethod(Object bean, String methodName, List<Object[]> methodParams)
            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException {
        if (CollectionUtil.isNotEmpty(methodParams)) {
            Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams));
            method.invoke(bean, getMethodParamsValue(methodParams));
        } else {
            Method method = bean.getClass().getDeclaredMethod(methodName);
            method.invoke(bean);
        }
    }


    /**
     * 获取bean名称
     *
     * @param invokeTarget 目标字符串
     * @return bean名称
     */
    public static String getBeanName(String invokeTarget) {
        String beanName = StrUtil.subBefore(invokeTarget, "(", false);
        return StrUtil.subBefore(beanName, ".", true);
    }

    /**
     * 获取bean方法
     *
     * @param invokeTarget 目标字符串
     * @return method方法
     */
    public static String getMethodName(String invokeTarget) {
        String methodName = StrUtil.subBefore(invokeTarget, "(", false);
        return StrUtil.subAfter(methodName, ".", true);
    }

    /**
     * 获取method方法参数相关列表
     *
     * @param executorParam 目标字符串
     * @return method方法相关参数列表
     */
    public static List<Object[]> getMethodParams(String executorParam) {

        List<Object[]> list = new LinkedList<>();
        if (StrUtil.isEmpty(executorParam)) {
            return list;
        }

        // key=value形式的数组
        String[] methodParams = executorParam.split(",");
        // 参数对象
        Map<String, Object> objectMap = new HashMap<>(8);
        for (String methodParam : methodParams) {
            String str = StrUtil.trimToEmpty(methodParam);
            String[] keyAndValue = str.split("=");
            String key = keyAndValue[0];
            String value = keyAndValue[1];
            objectMap.put(key, value);
        }
        list.add(new Object[]{objectMap, Map.class});
        // 返回
        return list;
    }

    /**
     * @param jobId
     * @param executorParam
     * @return
     */
    public static Map<String, Object> getMapParams(Long jobId, String executorParam) {

        // 第一次参数为jobId
        Map<String, Object> objectMap = new HashMap<>(8);
        objectMap.put("jobId", jobId);
        if (StrUtil.isEmpty(executorParam)) {
            return objectMap;
        }

        // key=value形式的数组
        String[] methodParams = executorParam.split(",");
        // 参数对象

        for (String methodParam : methodParams) {
            String str = StrUtil.trimToEmpty(methodParam);
            String[] keyAndValue = str.split("=");
            String key = keyAndValue[0];
            String value = keyAndValue[1];
            objectMap.put(key, value);
        }
        return objectMap;
    }

    /**
     * 获取参数类型
     *
     * @param methodParams 参数相关列表
     * @return 参数类型列表
     */
    public static Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
        Class<?>[] methodParamsClass = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            methodParamsClass[index] = (Class<?>) os[1];
            index++;
        }
        return methodParamsClass;
    }

    /**
     * 获取参数值
     *
     * @param methodParams 参数相关列表
     * @return 参数值列表
     */
    public static Object[] getMethodParamsValue(List<Object[]> methodParams) {
        Object[] methodParamsClass = new Object[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            methodParamsClass[index] = os[0];
            index++;
        }
        return methodParamsClass;
    }
}
